package algorithm.poj.p1000;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLDecoder;
import java.util.StringTokenizer;

/**
 * 分析：
 * 
 * 实现：
 * 
 * 经验：
 * 
 * 教训：
 * 
 * 分类：递归
 * 
 * @author wong.tong@gmail.com
 *
 */
public class P1659 {

	public static void main(String[] args) throws Exception {

		InputStream input = null;
		if (false) {
			input = System.in;
		} else {
			URL url = P1659.class.getResource("P1659.txt");
			File file = new File(URLDecoder.decode(url.getPath(), "UTF-8"));
			input = new FileInputStream(file);
		}
		
		BufferedReader stdin = new BufferedReader(new InputStreamReader(input));

		int T = Integer.valueOf(stdin.readLine().trim());
		for (int i = 0; i < T; i ++) {
			int N = Integer.valueOf(stdin.readLine());
			int[] x = new int[N];
			StringTokenizer st = new StringTokenizer(stdin.readLine());
			for (int j = 0; j < N; j ++) x[j] = Integer.valueOf(st.nextToken());
			int[][] r = new int[N][];
			for (int j = 0; j < N; j ++) r[j] = new int[N];
			
			if (find(x, r, 0)) {
				System.out.println("YES");
				for (int k = 0; k < N; k ++) {
					for (int j = 0; j < N; j ++) {
						if (j > 0) System.out.print(" ");
						System.out.print(r[k][j]);
					}
					System.out.print("\n");
				}
				System.out.print("\n");
			} else {
				System.out.println("NO\n");
			}
		}
	}

	//递归
	private static boolean find(int[] x, int[][] r, int k) {
		
		int N = x.length;
		if (k == N-2) {
			int v = x[N-1];
			for (int i = 0; i < N-1; i ++) {
				if (r[i][N-1] == 1) v --;
			}
			int u = x[N-2];
			for (int i = 0; i < N-2; i ++) {
				if (r[i][N-2] == 1) u --;
			}
			
			if (u != v) {
				return false;
			} else {
				if (u == 0 || u == 1) {
					r[N-2][N-2] = 0; r[N-2][N-1] = u;
					r[N-1][N-2] = u; r[N-1][N-1] = 0;
					return true;
				} else {
					return false;
				}
			}
		} else {
			int xk = x[k];
			for (int i = 0; i < k; i ++) {
				if (r[i][k] == 1) xk --;
			}
			if (xk < 0 || xk > N-k-1) return false;
			
			int[] c = new int[xk];
			for (int i = 0; i < xk; i ++) c[i] = i;
			while (c != null && c.length == xk) {
				for (int i = k+1; i <N; i ++) {
					r[i][k] = 0;
					r[k][i] = 0;
				}
				for (int i = 0; i < xk; i ++) {
					r[c[i]+k+1][k] = 1;
					r[k][c[i]+k+1] = 1;
				}
				if (find(x, r, k+1)) {
					return true;
				} else {
					c = next(c, N-k-1);
				}
			}
			return false;
		}
	}
	
	/**
	 * 获得当前组合c的下一个组合。
	 * 利用该函数可以依次获得[0, M)的所有组合
	 * @param c
	 * @param M
	 * @return
	 */
	private static int[] next(int[] c, int M) {

		int index = c.length-1;
		for (; index > -1; index --) {
			if (c[index] < M-(c.length-index)) {
				c[index] ++;
				for (int i = index+1; i < c.length;i ++) {
					c[i] = c[index] + i - index;
				}
				break;
			}
		}
		if (index == -1) {
			if (c.length < M) {
				int[] nc = new int[c.length+1];
				for (int i = 0; i < nc.length; i ++) {
					nc[i] = i;
				}
				return nc;
			} else {
				return null;
			}
		} else {
			return c;
		}
	}
}